<?php

namespace frontend\controllers;

use Yii;
use yii\web\Controller;
use yii\web\UploadedFile;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\models\Sensor;
use common\models\SensorVersion;
use common\models\Command;
use common\models\SocketConnection;
use common\models\AllEX;
use common\models\Config;
use common\models\ProFile;
use common\models\Group;
use common\models\GroupSensor;
use common\models\SensorInfo;
use yii\helpers\ArrayHelper;
use common\models\QuaranFile;
use common\models\Alert;
use common\models\UserLog;

/**
 * Sensor controller
 */
class SensorController extends Controller {

    /**
     * @inheritdoc
     */
    public function behaviors() {
        if (Config::getLicense()['sensorNowCount'] == 0) {
            $rules = [];
        } else {
            $rules = [
                [
                    'actions' => [''],
                    'allow' => true,
                    'roles' => ['?'],
                ],
                [
                    'actions' => ['index', 'detail', 'getone', 'version', 'page', 'protect', 'quarantine', 'del-sensor'],
                    'allow' => true,
                    'roles' => ['@'],
                ],
                [
                    'actions' => [],
                    'allow' => true,
                    'roles' => ['admin'],
                ],
            ];
        }
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['index', 'detail', 'getone', 'delgroup', 'addgroup', 'addgroups', 'version', 'page', 'protect', 'quarantine', 'sendbase', 'sendisolate', 'del-sensor'],
                'rules' => $rules,
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                // 'logout' => ['post'],
                // 'test' => ['post'],
                ],
            ],
        ];
    }

    /**
     * @inheritdoc
     */
    public function actions() {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
            ],
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
            ],
        ];
    }

    /**
     * Displays homepage.
     *
     * @return mixed
     */
    public $enableCsrfValidation = false;

    private function isAPI() {
        $headers = Yii::$app->request->headers;
        if (stristr($headers['accept'], 'application/json') !== false) {
            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        } else {
            Yii::$app->response->format = \yii\web\Response::FORMAT_XML;
        }
    }

    public function actionIndex() {
        $ProfileVersionList = Sensor::find()->select('ProfileVersion')->distinct()->orderBy('ProfileVersion')->all();
        $SensorVersionList = Sensor::find()->select('SensorVersion')->distinct()->orderBy('SensorVersion')->all();
        $SensorFileList = SensorVersion::find()->select(['Version', 'Version as text', 'Path', 'MD5'])->orderBy('created_at')->asArray()->all();
        $ProFileList = ProFile::find()->select(['Version', 'Version as text', 'Path'])->orderBy('created_at')->asArray()->all();
        $GroupList = Group::find()->orderBy('level')->all();
        $GroupList = ArrayHelper::toArray($GroupList);
        return $this->render('index', [
                    'ProfileVersionList' => $ProfileVersionList,
                    'SensorVersionList' => $SensorVersionList,
                    'SensorFileList' => $SensorFileList,
                    'ProFileList' => $ProFileList,
                    'GroupList' => $GroupList,
        ]);
    }

    public function actionDetail() {
        $GroupList = Group::find()->where(['type' => Group::TYPE_NONAUTO])->orderBy('level')->all();
        $GroupList = ArrayHelper::toArray($GroupList);
        return $this->render('detail', ['GroupList' => $GroupList]);
    }

    public function actionGetone($id = false, $sid = false) {
        $this->isAPI();
        if ($id != false) {
            $sensor = Sensor::findOne($id);
        } elseif ($sid != false) {
            $sensor = Sensor::find()->where(['SensorID' => $sid])->one();
        }
        if (empty($sensor)) {
            $sensor = new Sensor();
            $sensor->ComputerName = '未找到这台计算机';
        }
        $data['status'] = 'success';
        $data['sensor'] = ArrayHelper::toArray($sensor);
        $data['sensor']['groupList'] = ArrayHelper::toArray($sensor->getGroups()->all());
        $info = SensorInfo::find()->where(['SensorID' => $sensor->SensorID])->one();
        $data['sensor']['info'] = empty($info) ? null : $info->data;
        if ($sid != false) {
            $data['sensor']['quaranFile'] = QuaranFile::find()->where(['=', 'sensor_id', $sid])->select('id,sensor_id,file_md5,file_path')->orderBy('id DESC')->asArray()->all();
        }
        return $data;
    }

    public function actionDelgroup() {
        $this->isAPI();
        if (!Yii::$app->request->isPost) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Not post request';
            return $data;
        }
        $post = json_decode(Yii::$app->request->getRawBody(), true);
        if (empty($post['gid'])) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'gid error';
            return $data;
        }
        if (empty($post['sid'])) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'sid error';
            return $data;
        }
        GroupSensor::deleteAll(['sid' => $post['sid'], 'gid' => $post['gid']]);
        $sensor = Sensor::findOne($post['sid']);
        $data['status'] = 'success';
        $data['groupList'] = ArrayHelper::toArray($sensor->getGroups()->all());
        return $data;
    }

    public function actionAddgroup() {
        $this->isAPI();
        if (!Yii::$app->request->isPost) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Not post request';
            return $data;
        }
        $post = json_decode(Yii::$app->request->getRawBody(), true);
        if (empty($post['gid'])) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'gid error';
            return $data;
        }
        if (empty($post['sid'])) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'sid error';
            return $data;
        }
        $groupSensor = GroupSensor::find()->where(['sid' => $post['sid'], 'gid' => $post['gid']])->one();
        if (isset($groupSensor)) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Have joined this group';
            return $data;
        }
        $groupSensor = new GroupSensor();
        $groupSensor->sid = $post['sid'];
        $groupSensor->gid = $post['gid'];
        $groupSensor->save();
        $sensor = Sensor::findOne($post['sid']);
        $data['status'] = 'success';
        $data['groupList'] = ArrayHelper::toArray($sensor->getGroups()->all());
        return $data;
    }

    public function actionAddgroups() {
        $this->isAPI();
        if (!Yii::$app->request->isPost) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Not post request';
            return $data;
        }
        $post = json_decode(Yii::$app->request->getRawBody(), true);
        $data['success'] = 0;
        $data['fail'] = 0;
        foreach ($post['sidList'] as $key => $sid) {
            $groupSensor = GroupSensor::find()->where(['sid' => $sid, 'gid' => $post['gid']])->one();
            if (isset($groupSensor)) {
                $data['fail'] ++;
                continue;
            }
            $groupSensor = new GroupSensor();
            $groupSensor->sid = $sid;
            $groupSensor->gid = $post['gid'];
            $groupSensor->save();
            $data['success'] ++;
        }
        $data['status'] = 'success';
        return $data;
    }

    public function actionVersion() {
        return $this->render('version');
    }

    public function actionPage($page = 1, $rows = 10, $whereList = []) {
        $this->isAPI();
        if (Yii::$app->request->isPost) {
            $post = json_decode(Yii::$app->request->getRawBody(), true);
            $page = empty($post['page']) ? $page : $post['page'];
            $rows = empty($post['rows']) ? $rows : $post['rows'];
        }
        $query = Sensor::find();
        if (count($whereList) > 0) {
            $query = $query->where($whereList[0]);
            for ($i = 1; $i < count($whereList); $i++) {
                $query = $query->andWhere($whereList[$i]);
            }
        }
        $page = (int) $page;
        $rows = (int) $rows;
        $count = (int) $query->count();
        $maxPage = ceil($count / $rows);
        $page = $page > $maxPage ? $maxPage : $page;
        $sensorList = $query->orderBy(['id' => SORT_DESC])->offSet(($page - 1) * $rows)->limit($rows)->asArray()->all();
        $data = [
            'data' => $sensorList,
            'count' => $count,
            'maxPage' => $maxPage,
            'pageNow' => $page,
            'status' => 'success'
        ];
        return $data;
    }

    public function actionProtect() {
        if (!Yii::$app->request->isPost) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Not post request';
            return $data;
        }
        $post = json_decode(Yii::$app->request->getRawBody(), true);
        if (empty($post)) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Rawbody not JSON';
            return $data;
        }
        $page = empty($post['page']) ? 1 : $post['page'];
        $rows = empty($post['rows']) ? 15 : $post['rows'];
        $whereList = [['isolate' => 0], ['NOT', ['SensorID' => null]]];
        if (isset($post['ComputerName']) && $post['ComputerName'] != '*' && !preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $post['ComputerName'])) {
            $whereList[] = ['like', 'ComputerName', $post['ComputerName']];
        }
        if (isset($post['ComputerName']) && $post['ComputerName'] != '*' && preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $post['ComputerName'])) {
            $whereList[] = ['=', 'IP', $post['ComputerName']];
        }
        if (isset($post['ProfileVersion']) && $post['ProfileVersion'] != '*') {
            $whereList[] = ['ProfileVersion' => $post['ProfileVersion']];
        }
        if (isset($post['SensorVersion']) && $post['SensorVersion'] != '*') {
            $whereList[] = ['SensorVersion' => $post['SensorVersion']];
        }
        if (isset($post['status']) && $post['status'] != '*') {
            $whereList[] = ['status' => $post['status']];
        }
        if (isset($post['group']) && $post['group'] != '*') {
            $group = Group::findOne($post['group']);
            if (isset($group)) {
                $SensorIDList = $group->getSensorIDList();
            } else {
                $SensorIDList = [];
            }
            $whereList[] = ['SensorID' => $SensorIDList];
        }
        $page = empty($post['page']) ? 1 : $post['page'];
        $rows = empty($post['rows']) ? 15 : $post['rows'];
        return $this->actionPage($page, $rows, $whereList);
    }

    public function actionQuarantine() {
        if (!Yii::$app->request->isPost) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Not post request';
            return $data;
        }
        $post = json_decode(Yii::$app->request->getRawBody(), true);
        if (empty($post)) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Rawbody not JSON';
            return $data;
        }
        $page = empty($post['page']) ? 1 : $post['page'];
        $rows = empty($post['rows']) ? 15 : $post['rows'];

        $whereList = [['isolate' => 1]];

        return $this->actionPage($page, $rows, $whereList);
    }

    //卸载计算机、、、
    public function actionSendbase() {
        $this->isAPI();
        $data = ['status' => 'success'];
        if (!Yii::$app->request->isPost) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Not post request';
            return $data;
        }
        $post = json_decode(Yii::$app->request->getRawBody(), true);
        $types = [
            'UPDATE' => Command::MSG_M2S_UPDATE,
            'UNINIT' => Command::MSG_M2S_UNINIT,
            'ISOLATE_UP' => Command::MSG_M2S_ISOLATE_UP,
            'ISOLATE_DOWN' => Command::MSG_M2S_ISOLATE_DOWN,
            'UPDATE_PROFILE' => Command::MSG_M2S_UPDATE_PROFILE,
            'PAUSE_SENSOR' => Command::MSG_M2S_PAUSE_SENSOR,
            'RESUME_SENSOR' => Command::MSG_M2S_RESUME_SENSOR,
            'SCAN' => Command::MSG_M2S_SCAN,
        ];
        if (empty($types[$post['type']])) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Type error';
            return $data;
        }
        if (empty($post['SensorIDList'])) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'SensorIDList error';
            return $data;
        }
        $type = $types[$post['type']];
        $SensorIDList = $post['SensorIDList'];
        foreach ($SensorIDList as $key => $SensorID) {
            $command = new Command();
            $command->Type = $type;
            $command->SensorID = $SensorID;
            if ($type == Command::MSG_M2S_UPDATE) {
                $json = ['Version' => '', 'URL' => ''];
                $version = SensorVersion::find()->where(['status' => 1])->one();
                if (isset($version)) {
                    $json['Version'] = $post['SensorFile']['Version'];
                    $json['URL'] = Yii::$app->params['staticUrl'] . $post['SensorFile']['Path'];
                    $json['MD5'] = $post['SensorFile']['MD5'];
                }
                $command->data = $json;
            }
            if ($type == Command::MSG_M2S_UPDATE_PROFILE) {
                $json = ['Version' => '', 'URL' => ''];
                $version = SensorVersion::find()->where(['status' => 1])->one();
                if (isset($version)) {
                    $json['Version'] = $post['ProFile']['Version'];
                    $json['URL'] = Yii::$app->params['staticUrl'] . $post['ProFile']['Path'];
                }
                $command->data = $json;
            }
            if ($type == Command::MSG_M2S_ISOLATE_UP) {
                $data = Config::getBase();
                $json = [
                    'WhiteList' => $data['WhiteList'],
                    'PromptMessage' => $data['PromptMessage']
                ];
                if (!in_array(Yii::$app->params['selfIP'], $json['WhiteList'])) {
                    $json['WhiteList'][] = Yii::$app->params['selfIP'];
                }
                if (!in_array(Yii::$app->params['engineIP'], $json['WhiteList'])) {
                    $json['WhiteList'][] = Yii::$app->params['engineIP'];
                }
                // $json = [
                //     'WhiteList'=>[],
                //     'PromptMessage'=>'隔离测试！',
                // ];
                // $json['WhiteList'][] = '1.1.1.1';
                // $json[] = Yii::$app->params['selfIP'];
                // $json[] = Yii::$app->params['engineIP'];
                // $json[] = $data['WhiteList'][0];
                // $json[] = $data['WhiteList'][1];
                $command->data = $json;
            }
            $command->send();
            $command->save();
            $Sensor = Sensor::find()->where(['SensorID' => $SensorID])->one();
            $Sensor->work = ($command->status == 1) ? Sensor::WORK_ING : Sensor::WORK_ERROR;
            $Sensor->save();
            //日志
            $userLog = new UserLog();
            //$userLog->type = UserLog::Type_Logput;
            $userLog->status = UserLog::Success;
            if ($post['type'] == 'UNINIT') {
                $userLog->info = '成功卸载SensorID = ' . $SensorID . '的Sensor';
            } else if ($post['type'] == 'ISOLATE_UP') {
                $userLog->info = '成功隔离SensorID = ' . $SensorID . '的Sensor';
            } else if ($post['type'] == 'ISOLATE_DOWN') {
                $userLog->info = '成功解除隔离SensorID = ' . $SensorID . '的Sensor';
            }
            $userLog->save();
            if (($key + 1) < count($SensorIDList)) {
                usleep(20000);
            }
        }
        return $data;
    }

    public function actionSendisolate() {
        $this->isAPI();
        $data = ['status' => 'success'];
        if (!Yii::$app->request->isPost) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'Not post request';
            return $data;
        }
        $post = json_decode(Yii::$app->request->getRawBody(), true);
        if (empty($post['SensorIDList'])) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'SensorIDList error';
            return $data;
        }
        if (!array_key_exists('WhiteList', $post)) {
            $data['status'] = 'fail';
            $data['errorMessage'] = 'WhiteList error';
            return $data;
        }
        $type = Command::MSG_M2S_ISOLATE_UP;
        $SensorIDList = $post['SensorIDList'];
        $WhiteList = $post['WhiteList'];
        foreach ($SensorIDList as $key => $SensorID) {
            $command = new Command();
            $command->Type = $type;
            $command->SensorID = $SensorID;
            if (isset($WhiteList[$SensorID])) {
                $json = explode(",", $WhiteList[$SensorID]);
                $command->data = $json;
            }
            $command->send();
            $command->save();
            $Sensor = Sensor::find()->where(['SensorID' => $SensorID])->one();
            $Sensor->work = ($command->status == 1) ? Sensor::WORK_ING : Sensor::WORK_ERROR;
            $Sensor->save();
            if (($key + 1) < count($SensorIDList)) {
                usleep(20000);
            }
        }
        return $data;
    }

    public function actionDelSensor() {
        $this->isAPI();
        $data['status'] = 'fail';
        if (!Yii::$app->request->isDelete) {
            return $data;
        }
        $delete = json_decode(Yii::$app->request->getRawBody(), true);
        $uninit_count = Sensor::find()->where(['IN', 'SensorID', $delete['sid']])->andWhere(['=', 'status', Sensor::UNINIT])->count();
        if ($uninit_count < count($delete['sid'])) {
            $data['errorMessage'] = '请确认所选计算机均为卸载状态';
            return $data;
        }
        Sensor::deleteAll(['IN', 'SensorID', $delete['sid']]);
        SensorInfo::deleteAll(['IN', 'SensorID', $delete['sid']]);
        Alert::deleteAll(['IN', 'SensorID', $delete['sid']]);
        //日志
        $userLog = new UserLog();
        //$userLog->type = UserLog::Type_Logput;
        $userLog->status = UserLog::Success;
        $userLog->info = '成功删除SensorID = ' . json_encode($delete['sid'], true) . '的Sensor';
        $userLog->save();
        $data['status'] = 'success';
        return $data;
    }

}
